package career_service

import (
	"encoding/json"
	"fmt"
	"peilian-api/app/global/common"
	"peilian-api/app/global/databases/tables"
	"peilian-api/app/global/errors"
	"peilian-api/app/global/log"
	"peilian-api/app/global/variable"
	"peilian-api/app/model"
	"peilian-api/app/services/report_service"
	"peilian-api/utils/tools"
	"strconv"
	"strings"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

const (
	DefaultTab = `[
  {
    "id": 1,
    "name": "通用岗位"
  },
  {
    "id": 2,
    "name": "公务员"
  },
  {
    "id": 3,
    "name": "互联网运营"
  },
  {
    "id": 4,
    "name": "产品经理"
  },
  {
    "id": 5,
    "name": "项目经理"
  },
  {
    "id": 6,
    "name": "销售"
  },
  {
    "id": 7,
    "name": "人力资源"
  },
  {
    "id": 9,
    "name": "行政"
  },
  {
    "id": 10,
    "name": "财务"
  },
  {
    "id": 11,
    "name": "游戏策划"
  },
  {
    "id": 12,
    "name": "银行管培生"
  },
  {
    "id": 13,
    "name": "市场营销"
  }
]`
)

type CareerService struct{}

// 获取分类标签
func GetCareerLabel(ctx *gin.Context, theme string) ([]*model.GroupsLabel, error) {
	agentId, _ := ctx.Get("aid")
	if agentId == nil {
		agentId = 0
	}
	userId, _ := ctx.Get("uid")
	if userId == nil {
		userId = 0
	}
	var recommendCareerStr string
	var userInfo = tables.User{}
	variable.DB.MySQL.Model(&tables.User{}).Where("id=?", userId).Pluck("recommend_career", &recommendCareerStr).Find(&userInfo)
	recommendCareerLi := make([]string, 0)
	if recommendCareerStr != "" {
		recommendCareerLi = strings.Split(recommendCareerStr, ",")
	}
	career := make([]tables.Career, 0)
	if err := variable.DB.MySQL.Where("career_type = 'interview' and is_available <> 2 and agent_id in (0, ?) and is_release=? and FIND_IN_SET(?, not_show_agent_ids) = 0", agentId, true, agentId).
		Order("order_id asc").Find(&career).Error; err != nil {
		return nil, err
	}

	var out []*model.GroupsLabel
	recommendCareer := make([]*model.CareerResp, 0)
	labelCareerMap := make(map[string][]*model.CareerResp)
	labelOrderLi := make([]string, 0)
	for _, c := range career {
		careerResp := &model.CareerResp{
			Id:             c.ID,
			Name:           c.Name,
			CareerPhoto:    c.CareerPhoto,
			CareerMsg:      *c.CareerMsg,
			IsAvailable:    c.IsAvailable,
			Type:           c.Type,
			IsRelease:      c.IsRelease,
			PhotoIsDefault: nil,
		}
		if theme == "beida" {
			careerResp.CareerPhoto = c.CareerPhotoBeida
		}
		if _, ok := labelCareerMap[c.Label]; ok {
			labelCareerMap[c.Label] = append(labelCareerMap[c.Label], careerResp)
		} else {
			labelCareerMap[c.Label] = []*model.CareerResp{careerResp}
			labelOrderLi = append(labelOrderLi, c.Label)
		}
		if len(recommendCareerLi) > 0 && tools.Contains(recommendCareerLi, c.Name) {
			recommendCareer = append(recommendCareer, careerResp)
		}
	}
	if len(recommendCareer) > 0 {
		out = append(out, &model.GroupsLabel{
			Label: "为你推荐",
			Value: recommendCareer,
		})
	}
	for _, lo := range labelOrderLi {
		out = append(out, &model.GroupsLabel{
			Label: lo,
			Value: labelCareerMap[lo],
		})
	}
	return out, nil
}

func GetCareer(ctx *gin.Context) (*[]model.CareerResp, error) {
	agentId, _ := ctx.Get("aid")
	roleId, _ := ctx.Get("rid")
	var career []tables.Career
	err := variable.DB.MySQL.Where("career_type = 'interview' and is_available <> ? and agent_id = 0", 2).Order("order_id asc").Find(&career).Error
	if err != nil {
		return nil, err
	}
	out := make([]model.CareerResp, 0)
	inList := func(sL []string, s string) bool {
		for _, ss := range sL {
			if ss == s {
				return false
			}
		}
		return true
	}
	for i := 0; i < len(career); i++ {
		var care model.CareerResp
		care.Id = career[i].ID
		care.Name = career[i].Name
		care.CareerPhoto = career[i].CareerPhoto
		care.CareerMsg = *career[i].CareerMsg
		care.IsAvailable = career[i].IsAvailable
		care.Type = career[i].Type
		if career[i].AgentId == 0 && roleId.(uint) != 2 && career[i].Type == "自定义" {
			care.Type = "超级管理员自定义岗位"
		}
		if inList(strings.Split(career[i].NotShowAgentIds, ","), fmt.Sprintf("%v", agentId)) {
			care.AdminCareerShow = true
		}
		care.IsRelease = career[i].IsRelease
		care.PhotoIsDefault = career[i].PhotoIsDefault
		care.AgentId = career[i].AgentId
		out = append(out, care)
	}
	return &out, nil
}

type GetCareerPageReq struct {
	Page         int   `form:"page,default=0"`
	Size         int   `form:"size,default=10"`
	ProfessionId *uint `json:"profession_id" form:"profession_id"`
}

type GetCareerPageResp struct {
	Total int64              `json:"total"`
	Data  []model.CareerResp `json:"data"`
}

func GetCareerPage(ctx *gin.Context, req GetCareerPageReq) (*GetCareerPageResp, error) {
	agentId, _ := ctx.Get("aid")
	roleId, _ := ctx.Get("rid")
	var career []tables.Career
	q := variable.DB.MySQL.Model(&tables.Career{}).Where("career_type = 'interview' and is_available <> ? and agent_id = ?", 2, agentId).Order("order_id asc")
	if req.ProfessionId != nil {
		// 获取专业的所有子分类
		ProfessionIds, err := tables.GetProfessionChildIds(*req.ProfessionId)
		if err != nil {
			return nil, err
		}
		q = q.Where("profession_id in (?)", ProfessionIds)
	}
	var total int64
	err := q.Count(&total).Error
	if err != nil {
		return nil, err
	}

	if req.Size == 0 {
		req.Size = 10
	}
	offset := (req.Page - 1) * req.Size
	err = q.Offset(offset).Limit(req.Size).Preload("Profession").Find(&career).Error
	if err != nil {
		return nil, err
	}
	out := make([]model.CareerResp, 0)
	inList := func(sL []string, s string) bool {
		for _, ss := range sL {
			if ss == s {
				return false
			}
		}
		return true
	}
	for i := 0; i < len(career); i++ {
		var care model.CareerResp
		care.Id = career[i].ID
		care.Name = career[i].Name
		care.CareerPhoto = career[i].CareerPhoto
		care.CareerMsg = *career[i].CareerMsg
		care.IsAvailable = career[i].IsAvailable
		care.Type = career[i].Type
		if career[i].AgentId == 0 && roleId.(uint) != 2 && career[i].Type == "自定义" {
			care.Type = "超级管理员自定义岗位"
		}
		if inList(strings.Split(career[i].NotShowAgentIds, ","), fmt.Sprintf("%v", agentId)) {
			care.AdminCareerShow = true
		}
		care.IsRelease = career[i].IsRelease
		care.PhotoIsDefault = career[i].PhotoIsDefault
		care.AgentId = career[i].AgentId
		care.ProfessionId = career[i].ProfessionId
		if career[i].ProfessionId != nil {
			care.Profession = &model.Profession{
				Id:         career[i].Profession.ID,
				Name:       career[i].Profession.Name,
				Tier:       career[i].Profession.Tier,
				BelongToID: career[i].Profession.BelongToID,
			}
		}

		out = append(out, care)
	}
	resp := &GetCareerPageResp{
		Total: total,
		Data:  out,
	}
	return resp, nil
}

// 获取用户的career
func (c *CareerService) GetUserCareerList(ctx *gin.Context) ([]model.CareerSpecialTab, *errors.ErrRes) {
	var out []model.CareerSpecialTab
	// 1. 获取用户的uid
	uid, exists := ctx.Get("uid")
	if !exists {
		return out, errors.NewErrInfo(errors.SessionUidErrorCode, fmt.Errorf("uid错误,请登录后尝试"))
	}
	// 2. 获取默认tab+uid
	sc := variable.DB.Redis.Get(fmt.Sprintf(common.RedisSpecialTabKey, uid.(uint)))
	s, _ := sc.Result()
	if len(s) == 0 {
		s = DefaultTab
	}
	err := json.Unmarshal([]byte(s), &out)
	if err != nil {
		return out, errors.NewErrInfo(10003, fmt.Errorf("请刷新重试~"))
	}
	return out, nil
}

// 保存用户的专项career
func (c *CareerService) SaveUserSpecialCareer(ctx *gin.Context, arr []int64) *errors.ErrRes {
	// 1. 获取用户的uid
	uid, exists := ctx.Get("uid")
	if !exists {
		return errors.NewErrInfo(errors.SessionUidErrorCode, fmt.Errorf("uid错误,请登录后尝试"))
	}
	// 2. 将数据保存或者更新到数据库
	var whereMap map[string]interface{}
	var updateMap map[string]interface{}
	whereMap = make(map[string]interface{}, 0)
	updateMap = make(map[string]interface{}, 0)

	b, _ := json.Marshal(arr)
	whereMap["conf_key"] = tables.ConfKeySpecialTab
	whereMap["type"] = 1
	whereMap["remarks"] = uid

	// 更新数据
	updateMap["conf_key"] = tables.ConfKeySpecialTab
	updateMap["type"] = 1
	updateMap["remarks"] = strconv.Itoa(int(uid.(uint)))
	updateMap["conf_value"] = string(b)
	updateMap["extend_info"] = "用户"

	err := new(tables.CommonConf).UpsertByWhere(whereMap, updateMap)
	if err != nil {
		return errors.NewErrInfo(20012, err)
	}

	// 按查询格式输出数据
	idStr := ""
	for i := 0; i < len(arr); i++ {
		idStr = idStr + strconv.Itoa(int(arr[i])) + ","
	}
	idStr = strings.Trim(idStr, ",")

	// 查询数据，将数据更新入缓存
	var careerList []tables.Career
	if d := variable.DB.MySQL.Select("id, name").Where("id in (?)", arr).Order("field (id," + idStr + ")").Find(&careerList); d.Error != nil {
		return errors.NewErrInfo(20013, d.Error)
	}
	var careerSpecialTabList []model.CareerSpecialTab
	for i := 0; i < len(careerList); i++ {
		careerSpecialTabList = append(careerSpecialTabList, model.CareerSpecialTab{Id: careerList[i].ID, Name: careerList[i].Name})
	}
	// 将数据存入到redis
	byt, _ := json.Marshal(careerSpecialTabList)
	if sc := variable.DB.Redis.Set(fmt.Sprintf(common.RedisSpecialTabKey, uid.(uint)), string(byt), -1); sc.Err() != nil {
		return errors.NewErrInfo(20014, sc.Err())
	}
	return nil
}

// 设置 专项练习redis
func (c *CareerService) SetRedisSpecialKey() (int64, *errors.ErrRes) {
	var cs []tables.CommonConf
	var count int64 = 0
	variable.DB.MySQL.Model(&tables.CommonConf{}).Where("conf_key = ?", tables.ConfKeySpecialTab).FindInBatches(&cs, 10000, func(tx *gorm.DB, batch int) error {
		for i := 0; i < len(cs); i++ {
			var ids []int64 = make([]int64, 0)
			idStr := cs[i].ConfValue
			json.Unmarshal([]byte(idStr), &ids)
			idStr = strings.Trim(idStr, "[")
			idStr = strings.Trim(idStr, "]")
			var cstl []model.CareerSpecialTab
			if d2 := variable.DB.MySQL.Model(&tables.Career{}).Select("id, name").Where("id in (?)", ids).Order("field (id," + idStr + ")").Find(&cstl); d2.Error != nil {
				continue
			}
			byt, _ := json.Marshal(cstl)
			uid, _ := strconv.Atoi(cs[i].Remarks)
			sc := variable.DB.Redis.Set(fmt.Sprintf(common.RedisSpecialTabKey, uid), string(byt), -1)
			if _, err := sc.Result(); err != nil {
				continue
			}
			count++
		}
		return nil
	})
	return count, nil
}

func (c *CareerService) SetHistoryWebReport(ctx *gin.Context, cnt *int64) error {
	sessions := make([]*tables.Session, 0)
	if err := variable.DB.MySQL.Preload("Career").Find(&sessions).Error; err != nil {
		return err
	}
	for _, s := range sessions {
		if s.Career == nil {
			continue
		}
		if s.Career.ReportType == "web" && strings.HasSuffix(s.Url, "pdf") {
			*cnt += 1
		}
	}
	go func() {
		defer tools.RecoverGoroutine()
		for _, s := range sessions {
			if s.Career == nil {
				continue
			}
			if s.Career.ReportType == "web" && strings.HasSuffix(s.Url, "pdf") {
				sessionId := strconv.Itoa(int(s.ID))
				if err := report_service.GenerateReport(ctx, sessionId, true); err != nil {
					fmt.Println(err.Error())
				}
			}
		}
		log.ZapLogger.Info("新版web报告历史数据刷新完成")
	}()
	return nil
}

// 获取所有的职业
func (cs *CareerService) GetProfessionList(c *gin.Context) (int64, []model.ProfessionListResp, *errors.ErrRes) {
	var count int64
	var out = make([]model.ProfessionListResp, 0)
	str := "is_available = 0 and type != '自定义'"
	careerList, err := new(tables.Career).GetCareerInfoListByWhereStr(str)
	if err != nil {
		return 0, out, errors.NewErrInfo(10002, err)
	}
	for _, v := range careerList {
		var plr = model.ProfessionListResp{}
		plr.Id = v.ID
		plr.Name = v.Name
		plr.CareerPhone = v.CareerPhoto
		plr.Type = v.Type
		plr.Label = v.Label
		careerMsg := v.CareerMsg
		if careerMsg != nil {
			plr.CareerMsg = *v.CareerMsg
		}
		out = append(out, plr)
	}
	return count, out, nil
}
